package com.paper.tiger.easy.rpc.center.handler;

import com.alibaba.fastjson.JSON;
import com.paper.tiger.easy.rpc.center.common.RegisterObject;
import com.paper.tiger.easy.rpc.center.common.ServerMap;
import com.paper.tiger.easy.rpc.center.service.BaseService;
import com.paper.tiger.easy.rpc.core.RegisterData;
import com.paper.tiger.easy.rpc.core.ServerType;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 *  处理具体服务的handler
 */
public class ServerHanler extends SimpleChannelInboundHandler<RegisterData> {


    private static final InternalLogger log = InternalLoggerFactory.getInstance(ServerHanler.class);

    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(1, 2, 60,
            TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000), r -> new Thread(r,"baseServiceThread"),new ThreadPoolExecutor.AbortPolicy());

    /**
     * 接收到消息的时候调用
     * @param ctx
     * @param data
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RegisterData data) throws Exception {

        Integer type = data.getType();
        ServerType serverType = ServerType.getByCode(type);
        BaseService baseService = (BaseService) RegisterObject.SERVICE_MAP.get(serverType.getRegisterName());
        EXECUTOR.execute(()->baseService.service(ctx,data));
    }


    /**
     * 客户端如果下线，删除对应的服务信息
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception
    {
        log.info("客户端下线，删除对应的存根， 下线信息为：{}",JSON.toJSONString(ctx));

        ServerMap.removeChannel(ctx.channel());

        // 通知其他客户端，此台服务已经下线
        RegisterData data = ServerMap.getRegisterData(ctx.channel());
        data.setType(ServerType.SERVER_OFF_LINE.getCode());

        List<Channel> channels = ServerMap.selectChannels(data.getList());

        for (Channel channel : channels)
        {
            channel.writeAndFlush(data);
        }

    }
}
